/*
 *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.webrtc;

/**
 * CryptoOptions defines advanced cryptographic settings for native WebRTC.
 * These settings must be passed into RTCConfiguration. WebRTC is secur by
 * default and you should not need to set any of these options unless you are
 * specifically looking for an additional crypto feature such as AES_GCM
 * support. This class is the Java binding of native api/crypto/cryptooptions.h
 */
public final class CryptoOptions {
    /**
     * SRTP Related Peer Connection Options.
     */
    public final class Srtp {
        /**
         * Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used
         * if both sides enable it
         */
        private final boolean enableGcmCryptoSuites;
        /**
         * If set to true, the (potentially insecure) crypto cipher
         * SRTP_AES128_CM_SHA1_32 will be included in the list of supported ciphers
         * during negotiation. It will only be used if both peers support it and no
         * other ciphers get preferred.
         */
        private final boolean enableAes128Sha1_32CryptoCipher;
        /**
         * If set to true, encrypted RTP header extensions as defined in RFC 6904
         * will be negotiated. They will only be used if both peers support them.
         */
        private final boolean enableEncryptedRtpHeaderExtensions;

        private Srtp(boolean enableGcmCryptoSuites, boolean enableAes128Sha1_32CryptoCipher,
                     boolean enableEncryptedRtpHeaderExtensions) {
            this.enableGcmCryptoSuites = enableGcmCryptoSuites;
            this.enableAes128Sha1_32CryptoCipher = enableAes128Sha1_32CryptoCipher;
            this.enableEncryptedRtpHeaderExtensions = enableEncryptedRtpHeaderExtensions;
        }

        @CalledByNative("Srtp")
        public boolean getEnableGcmCryptoSuites() {
            return enableGcmCryptoSuites;
        }

        @CalledByNative("Srtp")
        public boolean getEnableAes128Sha1_32CryptoCipher() {
            return enableAes128Sha1_32CryptoCipher;
        }

        @CalledByNative("Srtp")
        public boolean getEnableEncryptedRtpHeaderExtensions() {
            return enableEncryptedRtpHeaderExtensions;
        }
    }

    /**
     * Options to be used when the FrameEncryptor / FrameDecryptor APIs are used.
     */
    public final class SFrame {
        /**
         * If set all RtpSenders must have an FrameEncryptor attached to them before
         * they are allowed to send packets. All RtpReceivers must have a
         * FrameDecryptor attached to them before they are able to receive packets.
         */
        private final boolean requireFrameEncryption;

        private SFrame(boolean requireFrameEncryption) {
            this.requireFrameEncryption = requireFrameEncryption;
        }

        @CalledByNative("SFrame")
        public boolean getRequireFrameEncryption() {
            return requireFrameEncryption;
        }
    }

    private final Srtp srtp;
    private final SFrame sframe;

    private CryptoOptions(boolean enableGcmCryptoSuites, boolean enableAes128Sha1_32CryptoCipher,
                          boolean enableEncryptedRtpHeaderExtensions, boolean requireFrameEncryption) {
        this.srtp = new Srtp(
                enableGcmCryptoSuites, enableAes128Sha1_32CryptoCipher, enableEncryptedRtpHeaderExtensions);
        this.sframe = new SFrame(requireFrameEncryption);
    }

    public static Builder builder() {
        return new Builder();
    }

    @CalledByNative
    public Srtp getSrtp() {
        return srtp;
    }

    @CalledByNative
    public SFrame getSFrame() {
        return sframe;
    }

    public static class Builder {
        private boolean enableGcmCryptoSuites;
        private boolean enableAes128Sha1_32CryptoCipher;
        private boolean enableEncryptedRtpHeaderExtensions;
        private boolean requireFrameEncryption;

        private Builder() {
        }

        public Builder setEnableGcmCryptoSuites(boolean enableGcmCryptoSuites) {
            this.enableGcmCryptoSuites = enableGcmCryptoSuites;
            return this;
        }

        public Builder setEnableAes128Sha1_32CryptoCipher(boolean enableAes128Sha1_32CryptoCipher) {
            this.enableAes128Sha1_32CryptoCipher = enableAes128Sha1_32CryptoCipher;
            return this;
        }

        public Builder setEnableEncryptedRtpHeaderExtensions(
                boolean enableEncryptedRtpHeaderExtensions) {
            this.enableEncryptedRtpHeaderExtensions = enableEncryptedRtpHeaderExtensions;
            return this;
        }

        public Builder setRequireFrameEncryption(boolean requireFrameEncryption) {
            this.requireFrameEncryption = requireFrameEncryption;
            return this;
        }

        public CryptoOptions createCryptoOptions() {
            return new CryptoOptions(enableGcmCryptoSuites, enableAes128Sha1_32CryptoCipher,
                    enableEncryptedRtpHeaderExtensions, requireFrameEncryption);
        }
    }
}
